package com.swak.frame.ratelimit.parser;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.core.annotation.AnnotationUtils;

import com.swak.frame.interceptor.SwakAnnotationUtils;
import com.swak.frame.ratelimit.RateLimitAnnotationParser;
import com.swak.frame.ratelimit.RateLimitCodeUtil;
import com.swak.frame.ratelimit.annotation.RateLimit;
import com.swak.frame.ratelimit.config.LimitOperation;

public class LimitRaterAnnotationParser implements RateLimitAnnotationParser {

	private static final Set<Class<? extends Annotation>> LIMIT_OPERATION_ANNOTATIONS = new LinkedHashSet<>(1);
	static {
		LIMIT_OPERATION_ANNOTATIONS.add(RateLimit.class);
	}

	/**
	 * {@link com.swak.frame.ratelimit.annotation.RateLimit} not support class,@Target is method
	 * 
	 */
	@Override
	public Collection<LimitOperation> parseAnnotations(Class<?> type) {
		return Collections.emptyList();
	}

	@Override
	public Collection<LimitOperation> parseAnnotations(Method method,Class<?> targetClass) {
		Collection<? extends Annotation> anns = SwakAnnotationUtils.parseAnnotations(method,
				LIMIT_OPERATION_ANNOTATIONS);
		if (CollectionUtils.isNotEmpty(anns)) {
			// 处理 RateLimit和SwakMethod
			final Collection<LimitOperation> operation = new ArrayList<>(1);
			anns.stream().filter(ann -> (ann instanceof RateLimit))
					.forEach(ann -> operation.add(parseRateLimitAnnotation(method, targetClass, ann)));
			return operation;
		}
		return Collections.emptyList();
	}

	private LimitOperation parseRateLimitAnnotation(Method method, Class<?> targetClass, Annotation ann) {
		RateLimit rateLimit = null;
		if (ann instanceof RateLimit) {
			rateLimit = (RateLimit) ann;
		}
		if (rateLimit == null) {
			return null;
		}
		String resource = RateLimitCodeUtil.getlimtResource(rateLimit, method, targetClass);
		return LimitOperation.newLimitOperation(resource, rateLimit, rateLimit.desc());
	}

	@Override
	public boolean isCandidateClass(Class<?> targetClass) {
		return AnnotationUtils.isCandidateClass(targetClass, LIMIT_OPERATION_ANNOTATIONS);
	}

}
